package com.uchedao.seller.ui.car.publish.vin.http;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.uchedao.seller.util.LogUtil;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.util.EntityUtils;

import java.io.IOException;


/**
 * Created by ZhangZhanghua on 2015/8/25 0025.
 */
public class AsyncHttpResponseHandler {
    protected static final int SUCCESS_MESSAGE = 0;
    protected static final int FAILURE_MESSAGE = 1;
    protected static final int START_MESSAGE = 2;
    protected static final int FINISH_MESSAGE = 3;

    private Handler handler;

    /**
     * Creates a new AsyncHttpResponseHandler
     */
    public AsyncHttpResponseHandler() {
        // Set up a handler to post events back to the correct thread if
        // possible
        if (Looper.myLooper() != null) {
            handler = new Handler() {
                public void handleMessage(Message msg) {
                    AsyncHttpResponseHandler.this.handleMessage(msg);
                }
            };
        }
    }

    //
    // Callbacks to be overridden, typically anonymously
    //

    /**
     * Fired when the request is started, override to handle in your own code
     */
    public void onStart() {
    }

    /**
     * Fired in all cases when the request is finished, after both success and
     * failure, override to handle in your own code
     */
    public void onFinish() {
    }

    /**
     * Fired when a request returns successfully, override to handle in your own
     * code
     *
     * @param content
     *            the body of the HTTP response from the server
     */
    public void onSuccess(String content) {
    }

    /**
     * Fired when a request returns successfully, override to handle in your own
     * code
     *
     * @param statusCode
     *            the status code of the response
     * @param content
     *            the body of the HTTP response from the server
     */
    public void onSuccess(int statusCode, String content) {
        try {
            onSuccess(content);
        } catch (Throwable e) {
            onFailure(new HttpFailureException(e), content);
        }
    }

    /**
     * Fired when a request fails to complete, override to handle in your own
     * code
     *
     * @param error
     *            the underlying cause of the failure
     * @deprecated use {@link #(Throwable, String)}
     */
    public void onFailure(HttpFailureException error) {
    }

    /**
     * Fired when a request fails to complete, override to handle in your own
     * code
     *
     * @param error
     *            the underlying cause of the failure
     * @param content
     *            the response body, if any
     */
    public void onFailure(HttpFailureException error, String content) {
        // By default, call the deprecated onFailure(Throwable) for
        // compatibility
        onFailure(error);
    }

    //
    // Pre-processing of messages (executes in background threadpool thread)
    //

    protected void sendSuccessMessage(String responseBody) {
        sendMessage(obtainMessage(SUCCESS_MESSAGE, responseBody));
    }

    protected void sendSuccessMessage(int statusCode, String responseBody) {
        sendMessage(obtainMessage(SUCCESS_MESSAGE, new Object[] { new Integer(statusCode), responseBody }));
    }

    protected void sendFailureMessage(Throwable e, String responseBody) {
        sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[] { e, responseBody }));
    }

    protected void sendFailureMessage(Throwable e, byte[] responseBody) {
        sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[] { e, responseBody }));
    }

    protected void sendStartMessage() {
        sendMessage(obtainMessage(START_MESSAGE, null));
    }

    protected void sendFinishMessage() {
        sendMessage(obtainMessage(FINISH_MESSAGE, null));
    }

    //
    // Pre-processing of messages (in original calling thread, typically the UI
    // thread)
    //

    protected void handleSuccessMessage(int statusCode, String responseBody) {
        onSuccess(statusCode, responseBody);
    }

    protected void handleFailureMessage(HttpFailureException e, String responseBody) {
        onFailure(e, responseBody);
    }

    // Methods which emulate android's Handler and Message methods
    protected void handleMessage(Message msg) {
        Object[] response;
        switch (msg.what) {
            case SUCCESS_MESSAGE:
                response = (Object[]) msg.obj;
                handleSuccessMessage(((Integer) response[0]).intValue(), (String) response[1]);
                break;
            case FAILURE_MESSAGE:
                response = (Object[]) msg.obj;
                handleFailureMessage((HttpFailureException) response[0], (String) response[1]);
                break;
            case START_MESSAGE:
                onStart();
                break;
            case FINISH_MESSAGE:
                onFinish();
                break;
        }
    }

    protected void sendMessage(Message msg) {
        if (handler != null) {
            handler.sendMessage(msg);
        } else {
            handleMessage(msg);
        }
    }

    protected Message obtainMessage(int responseMessage, Object response) {
        Message msg = null;
        if (handler != null) {
            msg = this.handler.obtainMessage(responseMessage, response);
        } else {
            msg = new Message();
            msg.what = responseMessage;
            msg.obj = response;
        }
        return msg;
    }

    // Interface to AsyncHttpRequest
    void sendResponseMessage(HttpResponse response) {
        LogUtil.e("sendResponseMessage");
        StatusLine status = response.getStatusLine();
        String responseBody = null;
        try {
            HttpEntity entity = null;
            HttpEntity temp = response.getEntity();
            if (temp != null) {
                entity = new BufferedHttpEntity(temp);
                responseBody = EntityUtils.toString(entity, "UTF-8");
            }
        } catch (IOException e) {
            LogUtil.e("IOException");
            sendFailureMessage(new HttpFailureException(e), (String) null);
        }

        if (status.getStatusCode() >= 300) {
            LogUtil.e("status.getStatusCode() >= 300");
            sendFailureMessage(new HttpFailureException(status.getStatusCode(), status.getReasonPhrase()), responseBody);
        } else {
            LogUtil.e("status.getStatusCode() < 300");
            sendSuccessMessage(status.getStatusCode(), responseBody);
        }
    }
}